package com.hobbit.analyze
{
	import com.hobbit.analyze.analyzers.AnalyzeDictionary;
	import com.hobbit.analyze.analyzers.IAnalyze;
	import com.hobbit.analyze.base.AssetsLoader;
	import com.hobbit.analyze.base.Config;
	import com.hobbit.analyze.base.LoadItem;
	import com.hobbit.analyze.base.RemoteURLLoader;
	import com.hobbit.analyze.base.ResKey;
	import com.hobbit.analyze.event.AssetsEvent;
	import com.hobbit.utils.Priority;
	
	import flash.events.EventDispatcher;
	import flash.utils.Dictionary;
	import flash.utils.getTimer;

	/**
	 * 资源管理器 
	 * @author 晓晔
	 * 
	 */
	public class AssetsManager extends EventDispatcher
	{
		
		/**
		 * 配置文件加载组 
		 */		
		public static const GROUP_XML_CONFIG:String = "config";
		/**
		 * loading预加载组 
		 */		
		public static const GROUP_LOADING:String = "loading";
		/**
		 *  初始化预加载组
		 */		
		public static const GROUP_MAIN:String = "main";
		/**
		 * 异步加载的预加载组 
		 */		
		public static const GROUP_ASYNS_RES:String = "asyn";
		
		
		public function AssetsManager()
		{
			if(_instance == null)
			{
				_instance = this;
				init();
			}else
			{
				throw new Error("实例化单例类出错---> AssetsManager");
			}
		}
		private static var _instance:AssetsManager;
		public static function getInstance():AssetsManager
		{
			if(_instance == null)
			{
				_instance = new AssetsManager();
			}
			return _instance;
		}
		
		//========================
		/**
		 * 文件加载器 
		 */
		private var _assetsLoader:AssetsLoader;
		
		/**
		 * 语言版本号 
		 */
		private var _lang:String = "cn";
		
		/**
		 * 本地url 
		 */
		private var _iniFolderUrl:String = "";
		
		/**
		 * 外部url 
		 */
		private var _outFolderUrl:String = "";
		
		
		private function init():void
		{
			_assetsLoader = new AssetsLoader(RemoteURLLoader);
			_assetsLoader.addEventListener(AssetsEvent.GROUP_COMPLETE,groupComplete);
			_assetsLoader.addEventListener(AssetsEvent.GROUP_PROGRESS,groupProgress);
			_assetsLoader.addEventListener(AssetsEvent.PROGRESS,onLoadProgress);
		}
		
		//===================
		/**
		 * 用于保存请求加载外部素材的加载项
		 * _matLoadItemDic[key+"$"+subKey] = LoadItem; 
		 */		
		private var _matLoadItemDic:Dictionary = new Dictionary();
		
		/**
		 * 用于保存请求加载外部素材的ResKey
		 * _matResKeyDic[LoadItem]  = ResKey
		 */		
		private var _matResKeyDic:Dictionary = new Dictionary();
		
		/**
		 *  用于保存请求加载外部素材的completeFunc
		 * _matFuncDic[LoadItem] = [completeFunc]; 
		 */		
		private var _matFuncDic:Dictionary = new Dictionary();
		
		/**
		 * 列表加载进度 
		 * @param event
		 * 
		 */		
		protected function onLoadProgress(event:AssetsEvent):void
		{
			var loadItem:LoadItem = event.data as LoadItem;
			if(_matLoadItemDic[loadItem.name])
			{
				var resKey:ResKey = _matResKeyDic[loadItem];
				var analyze:IAnalyze = AnalyzeDictionary.getInstance().getAnalyze(resKey.type);
				var data:* = analyze.getData(resKey.key,resKey.subKey);
				var completeFuncList:Array = _matFuncDic[loadItem];
				for (var i:int = 0; i < completeFuncList.length; i++) 
				{
					var func:Function = completeFuncList[i];
					if(resKey.other != null)
					{
						var backObj:Object = {};
						backObj["data"] = data;
						backObj["resKey"] = resKey;
						func(backObj);
					}else
					{
						func(data);
					}
				}
				delete _matLoadItemDic[loadItem.name];
				delete _matFuncDic[loadItem];
				delete _matResKeyDic[loadItem];
			}
		}
		
		/**
		 * 组加载进度 
		 * @param event
		 * 
		 */		
		private function groupProgress(event:AssetsEvent):void
		{
			if(event.groupName == GROUP_LOADING)
			{
				var loadingProgressEvent:AssetsEvent = new AssetsEvent(AssetsEvent.LOADING_PROGRESS);
				loadingProgressEvent.progress = event.progress;
				dispatchEvent(loadingProgressEvent);
			}
			
			if(event.groupName == GROUP_MAIN)
			{
				var mainProgressEvent:AssetsEvent = new AssetsEvent(AssetsEvent.MAIN_PROGRESS);
				mainProgressEvent.progress = event.progress;
				dispatchEvent(mainProgressEvent);
			}
		}
		
		/**
		 * 组加载完成 
		 * @param event
		 * 
		 */		
		private function groupComplete(event:AssetsEvent):void
		{
			var groupName:String = event.groupName;
			var dataList:Vector.<LoadItem> = event.data as Vector.<LoadItem>;
			if(groupName == GROUP_XML_CONFIG)
			{
				var xmlList:Vector.<XML> = new Vector.<XML>();
				for (var i:int = 0; i < dataList.length; i++) 
				{
					var item:LoadItem = dataList[i];
					xmlList.push((item.result as XML));
				}
				
				Config.getInstance().initXmlConfig(xmlList,configComplete);
			}
			
			//loading组加载完成
			if(groupName == GROUP_LOADING)
			{
				var assetsEvent:AssetsEvent = new AssetsEvent(AssetsEvent.LOADING_COMPLETE);
				assetsEvent.progress = "1";
				dispatchEvent(assetsEvent);
			}
			
			//Main组加载完成
			if(groupName == GROUP_MAIN)
			{
				var mainLoadEvent:AssetsEvent = new AssetsEvent(AssetsEvent.MAIN_COMPLETE);
				mainLoadEvent.progress = "1";
				mainLoadEvent.data = event.data;
				dispatchEvent(mainLoadEvent);
			}
			
			//请求加载的模块是否加载完成
			if(_moduleCallBackDic[groupName])
			{
				var modulecallBackFuncList:Array = _moduleCallBackDic[groupName];
				for (var n:int = 0; n < modulecallBackFuncList.length; n++) 
				{
					var moduleCallBackFunc:Function = modulecallBackFuncList[n];
					moduleCallBackFunc(dataList);
				}
				delete _moduleCallBackDic[groupName];
			}
			
			//请求加载预加载列表完成
			if(_preloadResDic[groupName])
			{
				var obj:Object = _preloadResDic[groupName];
				var resKeyList:Array = obj["resKeyList"];
				var completeFunc:Function = obj["completeFunc"];
				for each (var resKey:ResKey in resKeyList) 
				{
					var callAnalyze:IAnalyze = AnalyzeDictionary.getInstance().getAnalyze(resKey.type);
					var data:* = callAnalyze.getData(resKey.key,resKey.subKey);
					resKey.data = data;
				}
				completeFunc(resKeyList);
				delete _preloadResDic[groupName];
			}
			
			//异步请求预加载文件 加载完成
			if(groupName == GROUP_ASYNS_RES)
			{
				if(dataList && dataList.length)
				{
					for (var j:int = 0; j < dataList.length; j++) 
					{
						var loadItem:LoadItem = dataList[j];
						var callBackList:Array = _asyncResItemDic[loadItem.name];
						for (var k:int = 0; k < callBackList.length; k++) 
						{
							var resObj:Object = callBackList[k];
							var key:String = resObj["key"];
							var subKey:String = resObj["subKey"];
							var resCompleteFunc:Function = resObj["completeFunc"];
							var type:String = resObj["type"];
							var analyze:IAnalyze = AnalyzeDictionary.getInstance().getAnalyze(type);
							var resData:* = analyze.getData(key,subKey);
							resCompleteFunc(resData);
						}
						delete _asyncResItemDic[loadItem.name];
					}
					
				}
			}
		}
		
		/**
		 * 开始加载Main组文件 
		 * 
		 */		
		public function loadMainMoudle():void
		{
			//开始加载main组文件
			var mainList:Vector.<LoadItem> = Config.getInstance().getMoudleLoadItemList(GROUP_MAIN);
			_assetsLoader.loadGroup(mainList,GROUP_MAIN);
		}
		
		/**
		 * 初始化配置文件解析完成 
		 * 执行初始化加载 
		 * 
		 */		
		private function configComplete():void
		{
			var loadingList:Vector.<LoadItem> = Config.getInstance().getMoudleLoadItemList(GROUP_LOADING);
			_assetsLoader.loadGroup(loadingList,GROUP_LOADING);
			var assetsEvent:AssetsEvent = new AssetsEvent(AssetsEvent.CONFIG_COMPLETE);
			assetsEvent.progress = "1";
			dispatchEvent(assetsEvent);
		}
		
		
		//==================
		
		private var _moduleCallBackDic:Dictionary = new Dictionary();//保存请求模块加载的回调方法
		/**
		 * 请求加载模块资源 
		 * @param moduleName 模块名称
		 * @param callBackFunc callBackFunc回调参数为 Vector.<LoadItem>
		 * 
		 */		
		public function loadModule(moduleName:String,callBackFunc:Function = null):void
		{
			var moduleList:Vector.<LoadItem> = Config.getInstance().getMoudleLoadItemList(moduleName);
			if(moduleList && moduleList.length)
			{
				if(_moduleCallBackDic[moduleName])
				{
					var tempArr:Array = _moduleCallBackDic[moduleName];
					_moduleCallBackDic[moduleName] = tempArr.concat([callBackFunc]);
				}else
				{
					_moduleCallBackDic[moduleName] = [callBackFunc];
				}
				_assetsLoader.loadGroup(moduleList,moduleName);
			}
		}
		/**
		 * 注册一个解析类 
		 * @param key 解析文件类型
		 * @param analyzeClass
		 * 
		 */		
		public function registerAnalyze(key:String,analyzeClass:Class):void
		{
			AnalyzeDictionary.getInstance().registerAnalyze(key,analyzeClass);
		}
		
		/**
		 * 用于保存 预先加载列表中的 Reskey和completeFunc
		 * _preloadResDic[getTime()] = {"resKeyList":resKeyList,"completeFunc":completeFunc}
		 * (哎，蛋疼的各种 Dictionary)  
		 */		
		private var _preloadResDic:Dictionary = new Dictionary();
		/**
		 * 获取预先加载素材列表
		 * @param resKeyList ResKey类型 列表中多个Reskey表示 获取多个素材
		 * @param completeFunc Function参数为加载完成的资源列表
		 * 
		 */		
		public function getPreloadResList(resKeyList:Array,completeFunc:Function):void
		{
			var groupName:String = String(getTimer());
			var groupList:Vector.<LoadItem> = new Vector.<LoadItem>();
			_preloadResDic[groupName] = {"resKeyList":resKeyList,"completeFunc":completeFunc};
			for (var i:int = 0; i < resKeyList.length; i++) 
			{
				var resKey:ResKey = resKeyList[i];
				var loadItem:LoadItem = Config.getInstance().getLoadItemByName(resKey.key);
				groupList.push(loadItem);
			}
			_assetsLoader.loadGroup(groupList,groupName);
		}
		
		/**
		 * 同步获取预先加载素材 
		 * @param key 对应文件名
		 * @param subKey swf文件内的导出类名
		 * @param type 文件类型
		 * @return 
		 * 
		 */		
		public function getSynPreloadRes(key:String = "",subKey:String = "",type:String = "swf"):*
		{
			if(type == "")
			{
				type = Config.getInstance().getItemTypeByName(key);
			}
			
			var analyze:IAnalyze = AnalyzeDictionary.getInstance().getAnalyze(type);
			var data:*;
			if(analyze)
			{
				data = analyze.getData(key,subKey);
			}
			return data;
		}
		
		/**
		 * 当异步获取素材时 用来存放请求加载的LoadItem对应的 key,subKey,completeFunc,type
		 * _asyncResItemDic[LoadItem.name] = [{"key":key,"subKey":subKey,"compelteFunc":completeFunc,"type":type}]; 
		 */		
		private var _asyncResItemDic:Dictionary = new Dictionary();
		/**
		 * 异步获取预加载素材
		 * @param key  img,xml,json,ddd,sound,swf key对应文件名 
		 * 需要在subkey参数中传递 对应的swf对应资源中导出类 名
		 * @param completeFunc
		 * @param type
		 * @param subKey
		 * @param priority 加载优先级
		 * 
		 */		
		public function getAsyncPreloadRes(key:String,completeFunc:Function,type:String = "",subKey:String = "",priority:int = Priority.MEDIUM):void
		{
			if(type == "")
			{
				type = Config.getInstance().getItemTypeByName(key);
			}
			
			var data:* = getSynPreloadRes(key,type,subKey);
			if(data != null)
			{
				completeFunc(data);
			}else
			{
				var loadItem:LoadItem = Config.getInstance().getLoadItemByName(key);
				loadItem.priority = priority;
				var loadItemList:Vector.<LoadItem> = new Vector.<LoadItem>();
				
				if(loadItem.status == LoadItem.STATUS_NOT_LOADED)
				{
					loadItemList.push(loadItem);
				}
				
				if(_asyncResItemDic[loadItem.name])
				{
					var tempArr:Array = _asyncResItemDic[loadItem.name];
					tempArr.push(loadItem);
					_asyncResItemDic[loadItem.name] = tempArr;
				}else
				{
					_asyncResItemDic[loadItem.name] = [{"key":key,"subKey":subKey,"completeFunc":completeFunc,"type":type}];
				}
				
				_assetsLoader.loadGroup(loadItemList,GROUP_ASYNS_RES,priority);
			}
		}
		
		/**
		 * 获取某种类别的资源 
		 * @param type  LoadItem.TYPE_SWF LoadItem.TYPE_JSON .....
		 * 
		 */		
		public function getDataListByType(type:String):Dictionary
		{
			var returnDic:Dictionary;
			if(type != null && type != "")
			{
				var analyze:IAnalyze = AnalyzeDictionary.getInstance().getAnalyze(type);
				if(analyze != null)
				{
					returnDic = analyze.getDataList();
				}
			}
			return returnDic;
		}
		
		/**
		 * 获取外部素材
		 * @param key 一般是对应素材id
		 * @param completeFunc 回调函数
		 * @param subKey 对应素材的第二个索引
		 * @param priority 加载优先级
		 * @param type 素材类型 默认为： LoadItem.TYPE_SWF;
		 * @param other 其他标记信息 传参给回调方法
		 */		
		public function getMatRes(key:String,completeFunc:Function,subKey:String="",type:String=LoadItem.TYPE_SWF,priority:int = Priority.LOW,other:Object = null):void
		{
			var analyze:IAnalyze = AnalyzeDictionary.getInstance().getAnalyze(type);
			var data:* = analyze.getData(key,subKey);
			var resKey:ResKey = new ResKey(key,subKey,type,other);
			if(data)//素材已被加载解析过
			{
				if(resKey.other != null)
				{
					var backObj:Object = {};
					backObj["data"] = data;
					backObj["resKey"] = resKey;
					completeFunc(backObj);
				}else
				{
					completeFunc(data);
				}
				return;
			}
			
			var obj:Object = Config.getInstance().getMatObj(key,subKey);
			var indexKey:String = key + "$" + subKey;
			//			var indexKey:String = obj["swfurl"];
			if(obj==null)
			{
				completeFunc(null);
				return;
			}
			
			var ploadItem:LoadItem = _matLoadItemDic[indexKey];
			if(ploadItem!=null)
			{
				var funcList:Array = _matFuncDic[ploadItem]; 
				if(funcList)
				{
					funcList.push(completeFunc);
				}
				return;
			}
			
			var loadItem:LoadItem = new LoadItem(outFolderUrl + obj["swfurl"],indexKey,type,priority,null);
			_matLoadItemDic[indexKey] = loadItem;
			
			_matResKeyDic[loadItem] = resKey;
			
			_matFuncDic[loadItem] = [completeFunc];
			
			var itemList:Vector.<LoadItem> = new Vector.<LoadItem>();
			itemList.push(loadItem);
			_assetsLoader.insert(itemList);
		}
		
		/**
		 * 获取一组外部素材 
		 * @param resKeyList 数组里为 ResKey类型
		 * @param completeFunc
		 * @param priority 加载优先级
		 * @param type
		 */		
		public function getMatResList(resKeyList:Array,completeFunc:Function,priority:int = Priority.LOW,type:String = LoadItem.TYPE_SWF):void
		{
			var groupName:String = String(getTimer());
			var groupList:Vector.<LoadItem> = new Vector.<LoadItem>();
			_preloadResDic[groupName] = {"resKeyList":resKeyList,"completeFunc":completeFunc};
			for (var i:int = 0; i < resKeyList.length; i++) 
			{
				var resKey:ResKey = resKeyList[i];
				var obj:Object = Config.getInstance().getMatObj(resKey.key,resKey.subKey);
				if(obj != null)
				{
					var name:String = resKey.key + "$" + resKey.subKey;
					var loadItem:LoadItem = new LoadItem(outFolderUrl + obj["swfurl"],name,type,priority);
					groupList.push(loadItem);
				}
			}
			_assetsLoader.loadGroup(groupList,groupName);
		}
		
		/**
		 * 设置项目配置文件 
		 * @param configFileList ex::配置文件地址列表 ["ini.xml","outini.xml"]
		 * 
		 */		
		public function setInitConfig(configFileList:Array):void
		{
			var configList:Vector.<LoadItem> = new Vector.<LoadItem>();
			for (var i:int = 0; i < configFileList.length; i++) 
			{
				var loadItem:LoadItem = new LoadItem(configFileList[i],configFileList[i]);
				loadItem.groupName = GROUP_XML_CONFIG;
				loadItem.type = LoadItem.TYPE_XML;
				configList.push(loadItem);
			}
			_assetsLoader.loadGroup(configList,GROUP_XML_CONFIG);
		}
		
		/**
		 * 当前语言环境 
		 */
		public function get lang():String
		{
			return _lang;
		}
		
		/**
		 * @private
		 */
		public function set lang(value:String):void
		{
			_lang = value;
		}
		
		/**
		 * 内部文件路径 
		 */
		public function get iniFolderUrl():String
		{
			return _iniFolderUrl;
		}
		
		/**
		 * @private
		 */
		public function set iniFolderUrl(value:String):void
		{
			_iniFolderUrl = value;
		}
		
		/**
		 * 外部文件路径 
		 */
		public function get outFolderUrl():String
		{
			return _outFolderUrl;
		}
		
		/**
		 * @private
		 */
		public function set outFolderUrl(value:String):void
		{
			_outFolderUrl = value;
		}
	}
}